/******************************************************************************* * Copyright (c) 2007 - 2010 GreenDeltaTC. All rights reserved. This program and * the accompanying materials are made available under the terms of the Mozilla * Public License v1.1 which accompanies this distribution, and is available at * http://www.openlca.org/uploads/media/MPL-1.1.html * * Contributors: GreenDeltaTC - initial API and implementation * www.greendeltatc.com tel.: +49 30 4849 6030 mail: gdtc@greendeltatc.com ******************************************************************************/ package org.openlca.app.editors.graphical.model; import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.TimerTask; import org.eclipse.draw2d.ColorConstants; import org.eclipse.draw2d.CompoundBorder; import org.eclipse.draw2d.Figure; import org.eclipse.draw2d.Graphics; import org.eclipse.draw2d.GridData; import org.eclipse.draw2d.GridLayout; import org.eclipse.draw2d.Label; import org.eclipse.draw2d.LineBorder; import org.eclipse.draw2d.MouseEvent; import org.eclipse.draw2d.MouseListener; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.openlca.app.M; import org.openlca.app.editors.graphical.command.ChangeStateCommand; import org.openlca.app.editors.graphical.layout.Animation; import org.openlca.app.editors.graphical.model.ProcessExpander.Side; import org.openlca.app.rcp.images.Icon; import org.openlca.app.util.Labels; import org.openlca.core.model.ProcessType; class ProcessFigure extends Figure { static final int MINIMUM_HEIGHT = 25; static final int MINIMUM_WIDTH = 175; static final int MARGIN_HEIGHT = 2; static final int MARGIN_WIDTH = 4; private static final int TEXT_HEIGHT = 16; private static final Color LINE_COLOR = ColorConstants.gray; private static final Color TEXT_COLOR = ColorConstants.black; final ProcessNode node; private ProcessExpander leftExpander; private ProcessExpander rightExpander; private int minimumHeight = 0; ProcessFigure(ProcessNode processNode) { this.node = processNode; initializeFigure(); createHeader(); addMouseListener(new DoubleClickListener()); } private void initializeFigure() { setToolTip(new Label(Labels.processType(node.process.getProcessType()) + ": " + node.getName())); setForegroundColor(TEXT_COLOR); setBounds(new Rectangle(0, 0, 0, 0)); setSize(calculateSize()); GridLayout layout = new GridLayout(1, true); layout.horizontalSpacing = 10; layout.verticalSpacing = 0; layout.marginHeight = MARGIN_HEIGHT; layout.marginWidth = MARGIN_WIDTH; setLayoutManager(layout); paintBorder(); } private void createHeader() { Figure top = new Figure(); GridLayout topLayout = new GridLayout(3, false); topLayout.horizontalSpacing = 0; topLayout.verticalSpacing = 0; topLayout.marginHeight = 0; topLayout.marginWidth = 0; top.setLayoutManager(topLayout); leftExpander = new ProcessExpander(node, Side.LEFT); rightExpander = new ProcessExpander(node, Side.RIGHT); top.add(leftExpander, new GridData(SWT.LEFT, SWT.CENTER, false, false)); top.add(new Label(node.getName()), new GridData(SWT.FILL, SWT.FILL, true, false)); top.add(rightExpander, new GridData(SWT.RIGHT, SWT.CENTER, false, false)); add(top, new GridData(SWT.FILL, SWT.FILL, true, false)); GridData dummyGridData = new GridData(SWT.FILL, SWT.FILL, true, false); dummyGridData.heightHint = TEXT_HEIGHT + 3 * MARGIN_HEIGHT; add(new Figure(), dummyGridData); } private IOFigure getIOFigure() { for (Object child : getChildren()) if (child instanceof IOFigure) return (IOFigure) child; return null; } void refresh() { leftExpander.refresh(); rightExpander.refresh(); int x = getLocation().x; int y = getLocation().y; Dimension p = calculateSize(); int width = p.width; int height = p.height; if (getSize().width > width) width = getSize().width; if (getParent() == null) return; getParent().setConstraint(this, new Rectangle(x - 1, y - 1, width, height)); for (Link link : node.links) if (node.equals(link.targetNode)) link.refreshTargetAnchor(); else if (node.equals(link.sourceNode)) link.refreshSourceAnchor(); } @Override protected void paintFigure(Graphics graphics) { graphics.pushState(); graphics.setBackgroundColor(ColorConstants.white); graphics.fillRectangle(new Rectangle(getLocation(), getSize())); paintTop(graphics); if (!node.isMinimized() || Animation.isRunning()) paintTable(graphics); graphics.popState(); super.paintFigure(graphics); } private void paintBorder() { if (node.process.getProcessType() == ProcessType.LCI_RESULT) { LineBorder outer = new LineBorder(LINE_COLOR, 1); LineBorder innerInner = new LineBorder(LINE_COLOR, 1); LineBorder innerOuter = new LineBorder(ColorConstants.white, 1); CompoundBorder inner = new CompoundBorder(innerOuter, innerInner); CompoundBorder border = new CompoundBorder(outer, inner); setBorder(border); } else { LineBorder border = new LineBorder(LINE_COLOR, 1); setBorder(border); } } private void paintTop(Graphics graphics) { Image file = null; if (node.isMarked()) file = Icon.PROCESS_BG_MARKED.get(); else if (node.process.getProcessType() == ProcessType.LCI_RESULT) file = Icon.PROCESS_BG_LCI.get(); else file = Icon.PROCESS_BG.get(); int x = getLocation().x; int y = getLocation().y; int width = getSize().width; for (int i = 0; i < width - 20; i++) graphics.drawImage(file, new Point(x + i, y)); graphics.setForegroundColor(LINE_COLOR); graphics.drawLine(new Point(x, y + MINIMUM_HEIGHT), new Point(x + width - 1, y + MINIMUM_HEIGHT)); graphics.setForegroundColor(TEXT_COLOR); } private void paintTable(Graphics graphics) { graphics.setForegroundColor(LINE_COLOR); int margin = 5; int width = getSize().width; int height = getSize().height; int x = getLocation().x; int y = getLocation().y; graphics.drawLine(new Point(x + margin, y + MINIMUM_HEIGHT + TEXT_HEIGHT + MARGIN_HEIGHT), new Point(x + width - margin, y + MINIMUM_HEIGHT + TEXT_HEIGHT + MARGIN_HEIGHT)); if (height - margin > MINIMUM_HEIGHT + margin) graphics.drawLine(new Point(x + width / 2, y + MINIMUM_HEIGHT + margin), new Point(x + width / 2, y + height - margin)); graphics.setForegroundColor(TEXT_COLOR); graphics.drawText(M.Inputs, new Point(x + width / 6, y + MINIMUM_HEIGHT + MARGIN_HEIGHT)); graphics.drawText(M.Outputs, new Point(x + 2 * width / 3, y + MINIMUM_HEIGHT + MARGIN_HEIGHT)); graphics.setForegroundColor(ColorConstants.black); } @Override protected void paintChildren(Graphics graphics) { super.paintChildren(graphics); if (getIOFigure() == null) return; Rectangle clip = Rectangle.SINGLETON; if (getIOFigure().isVisible() && getIOFigure().intersects(graphics.getClip(clip))) { graphics.clipRect(getIOFigure().getBounds()); getIOFigure().paint(graphics); graphics.restoreState(); } } ProcessExpander getLeftExpander() { return leftExpander; } ProcessExpander getRightExpander() { return rightExpander; } ExchangeFigure[] getExchangeFigures() { List<ExchangeFigure> figures = new ArrayList<>(); for (ExchangeFigure o2 : getIOFigure().getChildren()) figures.add(o2); ExchangeFigure[] result = new ExchangeFigure[figures.size()]; figures.toArray(result); return result; } @Override public Dimension getPreferredSize(int hint, int hint2) { final Dimension cSize = calculateSize(); if (cSize.height > getSize().height || cSize.width > getSize().width || node.isMinimized()) return cSize; return getSize(); } Dimension calculateSize() { int offSet = 0; if (node.process.getProcessType() == ProcessType.LCI_RESULT) offSet = 3; int x = MINIMUM_WIDTH + offSet; if (getSize() != null && getSize().width > x) x = getSize().width; int y = MINIMUM_HEIGHT + offSet; if (node != null && !node.isMinimized()) y = getMinimumHeight(); return new Dimension(x, y); } int getMinimumHeight() { if (minimumHeight == 0) initializeMinimumHeight(); return minimumHeight; } private void initializeMinimumHeight() { int inputs = 0; int outputs = 0; for (ExchangeNode e : node.getChildren().get(0).getChildren()) if (!e.isDummy()) if (e.exchange.isInput()) inputs++; else outputs++; int length = Math.max(inputs, outputs); int offSet = 0; if (node.process.getProcessType() == ProcessType.LCI_RESULT) offSet = 3; int startExchanges = MINIMUM_HEIGHT + 4 * MARGIN_HEIGHT + TEXT_HEIGHT + offSet; minimumHeight = startExchanges + length * (TEXT_HEIGHT + 1); } private class DoubleClickListener implements MouseListener { private boolean firstClick = true; @Override public void mouseDoubleClicked(MouseEvent arg0) { } @Override public void mousePressed(MouseEvent arg0) { if (arg0.button == 1) { if (firstClick) { firstClick = false; TimerTask timerTask = new TimerTask() { @Override public void run() { firstClick = true; } }; Timer timer = new Timer(); timer.schedule(timerTask, 250); } else { ChangeStateCommand command = new ChangeStateCommand(node); node.parent().editor.getCommandStack().execute(command); } } } @Override public void mouseReleased(MouseEvent me) { } } }